/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.impl;

import io.iec.edp.caf.common.JSONSerializer;
import io.iec.edp.caf.commons.runtime.CafEnvironment;
import io.iec.edp.caf.commons.runtime.config.MsuConfigVariable;
import io.iec.edp.caf.commons.runtime.config.ServiceUnitConfigService;
import io.iec.edp.caf.commons.utils.CollectionUtils;
import io.iec.edp.caf.commons.utils.StringUtils;
import io.iec.edp.caf.msu.api.ServiceUnitAwareService;
import io.iec.edp.caf.msu.api.entity.*;
import io.iec.edp.caf.msu.api.enums.MsuType;
import lombok.extern.slf4j.Slf4j;
import lombok.var;

import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static java.util.stream.Collectors.toList;

/**
 * @author Leon Huo
 * @Date: 2021/5/12
 */
@Slf4j
public class ServiceUnitAwareServiceImpl implements ServiceUnitAwareService {

    private Lock locker = new ReentrantLock();
    private Boolean initialized = false;
    private List<ServiceUnitInfo> infos;
    private List<String> enableServiceUnitNames;
    private List<ServiceUnitInfo> enableServiceUnitInfos = new ArrayList<>();


//    //单例模式 装载时完成初始化
//    private static ServiceUnitAwareUtil INSTANCE = new ServiceUnitAwareUtil();
//
//    /**
//     * 构造函数
//     */
//    private ServiceUnitAwareServiceImpl() {
//    }
//
//    /**
//     * 公有构造方法
//     *
//     * @return
//     */
//    public static ServiceUnitAwareUtil getInstance() {
//        return INSTANCE;
//    }

    /**
     * 当前Server中包含的所有的服务单元信息
     */
    @Override
    public List<ServiceUnitInfo> getAllServiceUnits() {
        this.ensureInitialized();
        return this.infos;
    }

    /**
     * 当前已启用的服务单元名称列表
     */
    @Override
    public List<String> getEnabledServiceUnits() {
        this.ensureInitialized();
        return this.enableServiceUnitNames;
    }

    @Override
    public List<ServiceUnitInfo> getEnabledServiceUnitsInfo() {
        this.ensureInitialized();
        return this.enableServiceUnitInfos;
    }

    @Override
    public ServiceUnitRegisterInfo getServiceUnitRegisterInfo(String appName, String serviceName) {
        return makeUpServiceUnitRegisterInfo(appName, serviceName, getEnabledServiceUnitsInfo());
    }

    /**
     * 组装ServiceUnitRegisterInfo
     *
     * @param suInfoList
     * @return
     */
    private ServiceUnitRegisterInfo makeUpServiceUnitRegisterInfo(String appName, String serviceName, List<ServiceUnitInfo> suInfoList) {
        ServiceUnitRegisterInfo serviceUnitRegisterInfo = new ServiceUnitRegisterInfo();
        serviceUnitRegisterInfo.setAppName(appName);
        serviceUnitRegisterInfo.setServiceName(serviceName);
        serviceUnitRegisterInfo.setServiceUnitInfo(suInfoList);
        return serviceUnitRegisterInfo;
    }

    /**
     * 保证已被初始化
     */
    private void ensureInitialized() {
        if (!this.initialized) {
            try {
                locker.lock();
                if (!this.initialized) {
                    //查找已安装的所有SU详情
                    this.infos = new ArrayList<>();

                    //todo 这里不能用CafEnvironment.getServerRTPath()来获取path，因为在bean初始化之前就走了这个方法了，这个是后eviroment还没有
                    this.getServiceUnitInfo(this.infos, new File(CafEnvironment.getServerRTPath()));
                    //显示所有的su信息
//                    List<String> suNames = new ArrayList<>();
//                    infos.forEach(info->suNames.add(info.getName()));
                    //log.info("all service units: " + JSONSerializer.serialize(suNames));
                    //读取当前已启用的su配置列表
                    this.enableServiceUnitNames = this.readEnabledServiceUnits(this.infos);
                    this.infos.forEach(x -> {
                        var temp = this.enableServiceUnitInfos.stream().filter(y -> y.getName().equalsIgnoreCase(x.getName())).collect(toList());
                        if ((temp == null || temp.size() == 0) && this.enableServiceUnitNames.contains(x.getName())) {
                            this.enableServiceUnitInfos.add(x);
                        }
                    });
                    log.info("enable service units: " + JSONSerializer.serialize(this.enableServiceUnitNames));
                }
            } finally {
                this.initialized = true;
                locker.unlock();
            }
        }
    }

    /**
     * 递归获取服务单元信息
     *
     * @param infos
     * @param fileInfo
     */
    private void getServiceUnitInfo(List<ServiceUnitInfo> infos, File fileInfo) {
        ServiceUnitConfigService.getAllSuInfo().forEach(suInfo -> {
            ServiceUnitInfo info = this.readServiceUnitInfo(suInfo.get(MsuConfigVariable.SU_INFO));
            if (info != null) {
                //更新applitionPath
                info.setPath(suInfo.get(MsuConfigVariable.SU_INFO_PATH));
                infos.add(info);
            }
        });
    }

    /**
     * 读取已启用的服务单元列表
     * 默认enabled = fasle 认为是禁用的，否则都认为是启用的
     */
    private List<String> readEnabledServiceUnits(List<ServiceUnitInfo> infos) {
        return ServiceUnitConfigService.getEnableSu();
//        String content = ServiceUnitConfigService.getMsuJsonConfig();
//
//        if (StringUtils.isEmpty(content) || CollectionUtils.isEmpty(infos)) {
//            return Collections.emptyList();
//        }
//
//        //将所有识别到的su添加进来
//        List<String> suNames = infos.stream().map(ServiceUnitInfo::getName).collect(toList());
//        //白名单用的空列表
//        List<String> whiteNames = new ArrayList<>();
//
//        DeploymentConfiguration deployConfig = JSONSerializer.deserialize(content, CafMsuConfiguration.class).getDeploymentConfiguration();
//
//        for (ServiceUnitInfo suInfo : infos) {
//            for (ServiceUnitItem suItem : deployConfig.getServiceUnits()) {
//                if (suInfo.getName().equalsIgnoreCase(suItem.getName())) {
//                    if (suItem.getEnabled()) {
//                        whiteNames.add(suInfo.getName());
//                    } else {
//                        suNames.remove(suInfo.getName());
//                    }
//                }
//            }
//        }
//
//        switch (deployConfig.getStrategy()) {
//            case BlackList:
//                return suNames;
//            case WhiteList:
//                return whiteNames;
//        }
//
//        return null;
    }

    /**
     * 将JSON字符串转换为对象
     *
     * @param content
     * @return
     */
    private ServiceUnitInfo readServiceUnitInfo(String content) {
        if (content == null || "".equals(content))
            return null;

        content = content.substring(content.indexOf(":") + 1, content.lastIndexOf("}"));
        ServiceUnitInfo info = JSONSerializer.deserialize(content, ServiceUnitInfo.class);
        if (info == null)
            return null;
        if ("Common".equalsIgnoreCase(info.getType()))
            info.setMsuType(MsuType.Common);
        else
            info.setMsuType(MsuType.Biz);
//读取su配置文件时，必须按照大小区分的方式来读取，因为有人代码里没有忽略大小写
//        info.setName(info.getName().toLowerCase());
        if (info.getServiceUnitDes() == null || info.getServiceUnitDes().length() == 0) {
            info.setServiceUnitDes(info.getName());
        }
        return info;
    }

}
